package com.party.orders.controller;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.party.alipay.AlipayConfig;
import com.party.alipay.AlipayNotifyDTO;
import com.party.alipay.AlipayQueryVO;
import com.party.alipay.MyAlipayUtils;
import com.party.domain.CurrentAccount;
import com.party.domain.User;
import com.party.dto.Response;
import com.party.orders.service.ShopBusinessService;

/**
 * 
 * @author Caizhf
 * @date 2017年6月13日下午4:19:08
 * @version v.0.1
 * @email 1115054416@qq.com
 *
 *        <p>
 *        Description: 订单控制器
 *        </p>
 *
 */
@Controller
@RequestMapping("/orders")
public class OrdersController {

	@Autowired
	private ShopBusinessService shopBusinessService;

	private static final Logger logger = LoggerFactory.getLogger(OrdersController.class);

	/**
	 * 功能：删除订单
	 * 
	 * @param spid
	 * @return
	 */
	// 测试地址：127.0.0.1:8080/shop/delete/*
	@RequestMapping("/delete/{spid}")
	@ResponseBody
	public Response delete(@PathVariable("spid") int spid) {
		shopBusinessService.delete(spid);
		return Response.success();
	}

	/**
	 * 功能：按状态查询订单
	 * 
	 * @param ordersState
	 *            状态号
	 * @param pageNum
	 *            页码
	 * @return 包装类型对象的集合
	 */
	// 测试地址：127.0.0.1:8080/orders/list/*?ordersState=*&pageSize=*
	@RequestMapping("/list/{pageNum}")
	@ResponseBody
	public Response list(@RequestParam("ordersState") int ordersState, @PathVariable int pageNum,
			@RequestParam("pageSize") int pageSize) {
		User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		return Response.success(shopBusinessService.listOrders(user.getId(), ordersState, pageNum, pageSize));
	}

	/**
	 * 功能：显示单个订单的详情
	 * 增加了自动退款功能
	 * @param spid
	 * @return
	 */
	// 测试地址：127.0.0.1:8080/orders/get/*
	@RequestMapping("/get/{spid}")
	@ResponseBody
	public Response get(@PathVariable int spid) {
		return Response.success(shopBusinessService.findById(spid));
	}

	/**
	 * 功能：支付接口等等各种接口都需要调用这个接口修改状态
	 * 请注意：这是一个非常危险的方法，有用户可能会恶意修改订单状态而访问这个接口（上线的时候这个接口有待注释） 条件以及跳转的关系：
	 * 如果支付失败：传入1 如果支付成功并且有预约服务：传入2 如果预约的服务全部成功：传入3 如果支付成功并且没有预约服务：传入3
	 * 如果订单已经完成：传入4 如果正在退款中：传入5 如果已经退款：传入6 如果已经取消订单：传入7
	 * 
	 * @param state
	 *            1~7
	 * @return
	 */
	// 测试地址:127.0.0.1:8080/orders/update?state=*&spid=*
	@RequestMapping("/update")
	@ResponseBody
	public Response updateOnState(@RequestParam("state") int state, @RequestParam("spid") int spid) {
		shopBusinessService.updateOnState(state, spid);
		return Response.success();
	}

	/**
	 * 功能：取消订单
	 * 
	 * @param spid
	 * @return
	 */
	// 测试地址127.0.0.1:8080/calloff?spid=*
	@RequestMapping("/calloff")
	@ResponseBody
	public Response callOffOrders(@RequestParam("spid") int spid) {
		shopBusinessService.updateOnStateToCanceled(spid);
		return Response.success();
	}
	
	//--------------------------------------------------Pay Start-----------------------------------------------------//
	
	/**
	 * 功能：下单/支付宝、微信支付，集成优惠券使用功能
	 * 注意：微信支付请传入payWay=1，在下列注释中写入微信支付逻辑
	 * 
	 * @param spids：				清单的id号码数组
	 * @param cpids：				优惠券数组(可为空),约束：一定要保证传的是该用户领的的、未过期的劵（与allPriceCouponId互斥，不能同时传入）
	 * @param allPriceCouponId 		总减的优惠券（与cpids互斥，不能同时传入）
	 * @param payWay:				支付方式   0是支付宝，1是微信支付
	 * @param activityTime 			活动时间
	 * @param contactPhone			联系电话号码
	 * @param contactUser			联系人姓名
	 * @param contactNotes			备注信息
	 * @return
	 * @throws Exception
	 */
	// 测试地址：127.0.0.1:8080/orders/pay
	@RequestMapping("/pay")
	@Transactional(propagation=Propagation.REQUIRED) //扩大事务边缘
	public void doPay(Integer[] spids,Integer[] cpids,Integer allPriceCouponId, 
			@RequestParam("payWay")int payWay, String activityTime,
			String contactPhone,String contactUser,String contactNotes,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		// 查出该清单数组下所有商品的金额的总额、取出流水账单号与subject
		CurrentAccount ca = shopBusinessService.doPay(spids,cpids, payWay, user, allPriceCouponId,activityTime,contactPhone,contactUser,contactNotes);
		// 向第三方支付平台发起请求并且自动切换到支付流程(0表示支付宝，1表示微信支付)
		if (payWay == 0)
			// 支付宝支付封装
			MyAlipayUtils.alipay(ca.getAllOrderNum(), ca.getSubject(), ca.getTotalAmount().toString(), null, null,
					AlipayConfig.PRODUCT_CODE, response, request);
		else {
			// 微信支付在这里填写支付逻辑
			
		}
	}
	
	
	/**
	 * 支付宝异步通知网关
	 * 请注意：这里不适用微信，请额外写微信的回调接口
	 * @param request
	 * @param response
	 * ------------AlipayNotifyDTO
	 * @param out_trade_no
	 *            本站流水账订单号
	 * @param trade_no
	 *            支付宝交易单号
	 * @param trade_status
	 *            交易状态
	 * @param buyer_logon_id
	 * 			    所交易的支付宝账号
	 * @param gmt_payment
	 * 			    交易付款时间
	 * @param gmt_refund
	 * 			   交易退款时间
	 * @param total_amount
	 * 			  订单金额
	 * @return
	 * @throws AlipayApiException
	 * @throws IOException
	 */
	@RequestMapping(value="/ali_notify",method=RequestMethod.POST)
	public void notifyUrl(HttpServletRequest request, HttpServletResponse response, AlipayNotifyDTO dto) throws AlipayApiException, IOException {
		Map<String, String> params = new HashMap<String, String>();

		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}

		// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)
		// 计算得出通知验证结果
		// boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String
		// publicKey, String charset, String sign_type)
		boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET,
				AlipayConfig.SIGN_TYPE);
		if (verify_result) {// 验证成功
			// 请在这里加上商户的业务逻辑程序代码
			logger.info("验证成功！");
			// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

			if (dto.getTrade_status().equals("TRADE_FINISHED")) {
				// 注意：
				// 如果签约的是可退款协议，退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
				// 判断该笔订单是否在商户网站中已经做过处理
				// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
				// 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
				// 如果有做过处理，不执行商户的业务程序
				
				//如果已经支付过的，那么就把订单设置成已经完成的状态
				if(shopBusinessService.findCurrentAccountStateByAllOrdersNum(dto.getOut_trade_no()))
					shopBusinessService.updateCurrentAccountStateOnFinished(dto.getOut_trade_no());
				

			} else if (dto.getTrade_status().equals("TRADE_SUCCESS")) {
				// 注意：
				// 如果签约的是可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
				// 判断该笔订单是否在商户网站中已经做过处理
				// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
				
				//判断如果该订单还没有处理过的话
				if(!shopBusinessService.findCurrentAccountStateByAllOrdersNum(dto.getOut_trade_no()))
					//核心业务代码
					shopBusinessService.doPaySuccess(dto.getOut_trade_no(),dto.getTrade_no(),dto.getBuyer_logon_id(),dto.getGmt_payment(),dto.getTotal_amount());
				else{
					// 如果有做过处理，在这里执行需要的业务程序
				}
			}
			response.getOutputStream().print("success");	//不要修改这行代码,支付宝通过这七个字符判断是否验证成功
		} else {// 验证失败
			response.getOutputStream().print("fail");
		}

	}

	/**
	 * 支付宝同步通知页面跳转
	 * 请注意：这里不适用微信，请额外写微信的回调接口
	 * @param request
	 * @param out_trade_no
	 * @param trade_no
	 * @return
	 * @throws AlipayApiException
	 * @throws IOException 
	 */
	@RequestMapping("/ali_return")
	public String returnUrl(HttpServletRequest request, String out_trade_no, String trade_no,Model model)
			throws AlipayApiException, IOException {
		// 获取支付宝GET过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);
		}

		boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET,
				AlipayConfig.SIGN_TYPE);
		if (verify_result) {// 验证成功
			// 请在这里加上商户的业务逻辑程序代码
			// 该页面可做页面美工编辑
			// ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——
			
			//为了确认支付成功，在请求支付宝查询一次该订单状态
			AlipayQueryVO aliVo = MyAlipayUtils.query(out_trade_no, trade_no);
			if(aliVo==null||aliVo.getAlipay_trade_query_response()==null||
					!(aliVo.getAlipay_trade_query_response().getTrade_status().equals("TRADE_SUCCESS")||
							aliVo.getAlipay_trade_query_response().getTrade_status().equals("TRADE_FINISHED"))){
				//model在这里增加失败信息
				String msg = "支付失败，请回到订单查看状态";
				model.addAttribute("msg", msg);
				return "pay_failured";
			}
			
			//支付成功，返回商家手机号信息，用前端异步控制接入短信接口向商家发送短信
			List<String> phoneNums = shopBusinessService.findShopCartByCurrentAccountAllOrderNum(out_trade_no);
			model.addAttribute("phoneNums", phoneNums);
			return "/alipay_status/pay_success";
		} else {
			// 该页面可做页面美工编辑
			String msg = "对不起，支付宝验证失败，如果您已经支付，请您拿支付宝支付凭证与本站管理员联系，联系号码：********";
			model.addAttribute("msg", msg);
			return "/alipay_status/pay_failured";
		}
	}
	
	
	/**
	 * 功能：用户对某单项订单发起退款请求
	 * @param spid				退款的清单
	 * @param refundReason		退款原因说明
	 * @return					返回商家手机号，以便短信通知商家有退款请求
	 */
	@RequestMapping(value="/refund"/*,method = RequestMethod.POST*/)
	@ResponseBody
	public Response doRefund(int spid, String refundReason){
		//发起退款请求
		String adminPhone = shopBusinessService.doRefundRequestExecute(spid,refundReason);
		//在以下代码块中添加发送短信或者根据返回的手机号码去调用短信接口发送短信
		return Response.success(adminPhone);
	}

}
